"""
发布相关API接口
"""
from typing import List, Optional, Dict, Any
from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks
from sqlalchemy.orm import Session
from pydantic import BaseModel

from app.core.database import get_db
from app.services.deployment_service import DeploymentService
from app.models.release import ReleaseStatus, DeploymentStrategy, Environment

router = APIRouter()


# 请求模型
class CreateReleaseRequest(BaseModel):
    version: str
    description: Optional[str] = ""
    environment: Environment
    strategy: DeploymentStrategy
    config: Optional[Dict[str, Any]] = {}
    artifacts: Optional[Dict[str, Any]] = {}


class RollbackRequest(BaseModel):
    target_version: Optional[str] = None
    reason: str


class ReleaseResponse(BaseModel):
    id: int
    version: str
    description: Optional[str]
    environment: Environment
    strategy: DeploymentStrategy
    status: ReleaseStatus
    created_at: str
    deployed_at: Optional[str]
    completed_at: Optional[str]
    deployed_by: Optional[str]
    
    class Config:
        from_attributes = True


class ReleaseStatusResponse(BaseModel):
    release: Dict[str, Any]
    steps: List[Dict[str, Any]]
    health_checks: List[Dict[str, Any]]


@router.post("/releases", response_model=ReleaseResponse, status_code=status.HTTP_201_CREATED)
async def create_release(
    request: CreateReleaseRequest,
    db: Session = Depends(get_db),
    current_user: str = "system"  # 这里应该从认证中获取
):
    """创建发布记录"""
    try:
        deployment_service = DeploymentService(db)
        release = await deployment_service.create_release({
            **request.dict(),
            "deployed_by": current_user
        })
        
        return ReleaseResponse.from_orm(release)
        
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"创建发布记录失败: {str(e)}"
        )


@router.get("/releases", response_model=List[ReleaseResponse])
async def list_releases(
    environment: Optional[Environment] = None,
    status: Optional[ReleaseStatus] = None,
    limit: int = 50,
    offset: int = 0,
    db: Session = Depends(get_db)
):
    """获取发布列表"""
    try:
        deployment_service = DeploymentService(db)
        releases = await deployment_service.list_releases(
            environment=environment,
            status=status,
            limit=limit,
            offset=offset
        )
        
        return [ReleaseResponse.from_orm(release) for release in releases]
        
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取发布列表失败: {str(e)}"
        )


@router.get("/releases/{release_id}", response_model=ReleaseResponse)
async def get_release(
    release_id: int,
    db: Session = Depends(get_db)
):
    """获取发布详情"""
    try:
        deployment_service = DeploymentService(db)
        release = await deployment_service.get_release_status(release_id)
        
        if not release:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"发布记录不存在: {release_id}"
            )
        
        return ReleaseResponse.from_orm(release["release"])
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取发布详情失败: {str(e)}"
        )


@router.post("/releases/{release_id}/deploy", response_model=Dict[str, Any])
async def deploy_release(
    release_id: int,
    background_tasks: BackgroundTasks,
    db: Session = Depends(get_db),
    current_user: str = "system"
):
    """执行发布"""
    try:
        deployment_service = DeploymentService(db)
        
        # 在后台执行发布任务
        def deploy_task():
            import asyncio
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            try:
                return loop.run_until_complete(
                    deployment_service.deploy_release(release_id, current_user)
                )
            finally:
                loop.close()
        
        background_tasks.add_task(deploy_task)
        
        return {
            "message": "发布任务已启动",
            "release_id": release_id,
            "status": "in_progress"
        }
        
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"启动发布任务失败: {str(e)}"
        )


@router.get("/releases/{release_id}/status", response_model=ReleaseStatusResponse)
async def get_release_status(
    release_id: int,
    db: Session = Depends(get_db)
):
    """获取发布状态"""
    try:
        deployment_service = DeploymentService(db)
        status_data = await deployment_service.get_release_status(release_id)
        
        return ReleaseStatusResponse(**status_data)
        
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=str(e)
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取发布状态失败: {str(e)}"
        )


@router.post("/releases/{release_id}/rollback", response_model=Dict[str, Any])
async def rollback_release(
    release_id: int,
    request: RollbackRequest,
    background_tasks: BackgroundTasks,
    db: Session = Depends(get_db),
    current_user: str = "system"
):
    """执行回滚"""
    try:
        deployment_service = DeploymentService(db)
        
        # 在后台执行回滚任务
        def rollback_task():
            import asyncio
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            try:
                return loop.run_until_complete(
                    deployment_service.rollback_release(
                        release_id, 
                        request.reason, 
                        current_user
                    )
                )
            finally:
                loop.close()
        
        background_tasks.add_task(rollback_task)
        
        return {
            "message": "回滚任务已启动",
            "release_id": release_id,
            "reason": request.reason,
            "status": "in_progress"
        }
        
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"启动回滚任务失败: {str(e)}"
        )


@router.post("/releases/rollback", response_model=Dict[str, Any])
async def rollback_to_version(
    request: RollbackRequest,
    environment: Environment,
    background_tasks: BackgroundTasks,
    db: Session = Depends(get_db),
    current_user: str = "system"
):
    """回滚到指定版本"""
    try:
        if not request.target_version:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="必须指定目标版本"
            )
        
        deployment_service = DeploymentService(db)
        
        # 查找目标版本的发布记录
        releases = await deployment_service.list_releases(
            environment=environment,
            status=ReleaseStatus.SUCCESS
        )
        
        target_release = None
        for release in releases:
            if release.version == request.target_version:
                target_release = release
                break
        
        if not target_release:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"目标版本 {request.target_version} 不存在或未成功发布"
            )
        
        # 在后台执行回滚任务
        def rollback_task():
            import asyncio
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            try:
                return loop.run_until_complete(
                    deployment_service.rollback_release(
                        target_release.id,
                        request.reason,
                        current_user
                    )
                )
            finally:
                loop.close()
        
        background_tasks.add_task(rollback_task)
        
        return {
            "message": "回滚任务已启动",
            "target_version": request.target_version,
            "environment": environment,
            "reason": request.reason,
            "status": "in_progress"
        }
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"启动回滚任务失败: {str(e)}"
        )


@router.delete("/releases/{release_id}", response_model=Dict[str, Any])
async def cancel_release(
    release_id: int,
    db: Session = Depends(get_db),
    current_user: str = "system"
):
    """取消发布"""
    try:
        deployment_service = DeploymentService(db)
        
        # 这里应该实现取消发布的逻辑
        # 目前只是简单的状态更新
        from app.models.release import Release
        release = db.query(Release).filter(Release.id == release_id).first()
        
        if not release:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"发布记录不存在: {release_id}"
            )
        
        if release.status not in [ReleaseStatus.PENDING, ReleaseStatus.IN_PROGRESS]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"当前状态不允许取消: {release.status}"
            )
        
        release.status = ReleaseStatus.CANCELLED
        db.commit()
        
        return {
            "message": "发布已取消",
            "release_id": release_id,
            "status": "cancelled"
        }
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"取消发布失败: {str(e)}"
        )


@router.get("/releases/{release_id}/health", response_model=Dict[str, Any])
async def get_release_health(
    release_id: int,
    db: Session = Depends(get_db)
):
    """获取发布健康检查结果"""
    try:
        from app.services.health_check_service import HealthCheckService
        
        health_service = HealthCheckService(db)
        summary = health_service.get_health_check_summary(release_id)
        history = health_service.get_health_check_history(release_id, limit=20)
        
        return {
            "summary": summary,
            "recent_checks": [
                {
                    "id": check.id,
                    "name": check.check_name,
                    "status": check.status,
                    "response_time": check.response_time,
                    "checked_at": check.checked_at.isoformat() if check.checked_at else None
                }
                for check in history
            ]
        }
        
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取健康检查结果失败: {str(e)}"
        )
